package com.mz.mattress.client.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mz.mattress.api.common.Constants;
import com.mz.mattress.api.common.Result;
import com.mz.mattress.api.entity.*;
import com.mz.mattress.api.enums.DeviceOptionEnum;
import com.mz.mattress.api.enums.UseOrderStatusEnum;
import com.mz.mattress.api.mattress.OpenClientApi;
import com.mz.mattress.api.mattress.req.InspectionReq;
import com.mz.mattress.api.util.DateUtil;
import com.mz.mattress.api.util.MathUtil;
import com.mz.mattress.client.api.req.OrderUseRecordQueryReq;
import com.mz.mattress.client.interceptor.GlobalExecutor;
import com.mz.mattress.client.mapper.*;
import com.mz.mattress.client.service.MattressMsgService;
import com.mz.mattress.client.service.MemberMerService;
import com.mz.mattress.client.service.OrderUseTimesService;
import com.mz.mattress.client.timer.DeviceStartTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Slf4j
public class OrderUseTimesServiceImpl implements OrderUseTimesService {

    @Autowired
    private OrderUseTimesMapper orderUseTimesMapper;

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private MerchantGradeMapper merchantGradeMapper;

    @Autowired
    private SaleMapper saleMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private OrderUseTimesBonusMapper orderUseTimesBonusMapper;

    @Autowired
    private OpenClientApi openClientApi;

    @Autowired
    private MattressMsgService mattressMsgService;

    @Autowired
    private InspectReportMapper inspectReportMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private MemberMerService memberMerService;

    @Autowired
    private InvestorMapper investorMapper;

    @Override
    public Result<List<OrderUseTimes>> doingList(Long memberId) {
        List<OrderUseTimes> list = orderUseTimesMapper.doingList(memberId);
        return Result.ok(list);
    }

    @Override
    public Result<List<OrderUseTimes>> list(Long orderId) {
        List<OrderUseTimes> list = orderUseTimesMapper.list(orderId);
        return Result.ok(list);
    }

    @Override
    public Result<IPage<OrderUseTimes>> listPage(OrderUseRecordQueryReq req) {
        IPage<OrderUseTimes> listPage = orderUseTimesMapper.listPage(req.newPage(), req.getMemberId());
        return Result.ok(listPage);
    }

    @Override
    public Result<OrderUseTimes> detail(Integer id) {
        OrderUseTimes orderUseTimes = orderUseTimesMapper.selectById(id);

        Device device = deviceMapper.selectByDeviceCode(orderUseTimes.getDeviceCode());
        if (device != null) {
            orderUseTimes.setDevice(device);
        }

        return Result.ok(orderUseTimes);
    }

    @Override
    public Result queryStatus(Integer id) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        openClientApi.queryStatus(times.getDeviceCode(), times.getProductKey());

        return Result.ok();
    }

    @Override
    public Result inspection(InspectionReq req) {

        OrderUseTimes times = orderUseTimesMapper.selectById(req.getId());
        if (times == null) {
            return Result.fail("找不到记录");
        }

        req.setDeviceCode(times.getDeviceCode());
        req.setProductKey(times.getProductKey());

        openClientApi.sendInspection(req);

        //重置状态值
        OrderUseTimes update = new OrderUseTimes();
        update.setId(req.getId());
        update.setSex(req.getSex());
        update.setAge(req.getAge());
        update.setBirthday(req.getBirthday());
        update.setWeight(req.getWeight());
        update.setQuest1(req.getQuest1());
        update.setQuest2(req.getQuest2());
        update.setQuest3(req.getQuest3());
        update.setInspectStatus(1);
        update.setStatus(UseOrderStatusEnum.DOING.getValue());
        update.setResults(0);
        update.setRate(0);
        update.setCycle(0);
        update.setOxygen(0);
        update.setTired(0);
        orderUseTimesMapper.updateById(update);

        //更新会员信息
        Member member = new Member();
        member.setId(times.getMemberId());
        member.setSex(req.getSex());
        member.setBirthday(req.getBirthday());
        member.setWeight(req.getWeight());
        memberMapper.updateById(member);

        return Result.ok();
    }

    @Override
    public Result start(Integer id, Integer minute, Integer mode) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        if (times == null) {
            return Result.fail("找不到记录");
        }

        if (mode != null) {
            times.setMode(mode);
        }
        //异步执行
        DeviceStartTask task = new DeviceStartTask(openClientApi, times);
//        ThreadPoolShare.executeTask(task);
        GlobalExecutor.executeByCommon(task);

//        openClientApi.sendOptions(times.getDeviceCode(), times.getProductKey(), DeviceOptionEnum.start, null);

        OrderUseTimes update = new OrderUseTimes();
        update.setId(id);
        if (times.getStart() == null) {
            //第一次启动
            update.setStartTime(DateUtil.getNowDateTime());
            update.setEndTime(DateUtil.plusMin(DURATION));
            update.setDuration(DURATION);
            update.setStart(1);
            update.setPlan(0);
        }
//        update.setInspectStatus(1);
        if (mode != null) {
            update.setMode(mode);
        }
//        update.setMode(mode);
        update.setStatus(UseOrderStatusEnum.DOING.getValue());
        orderUseTimesMapper.updateById(update);

//        Device device1 = new Device();
//        device1.setId(times.getDeviceId());
//        device1.setWorkStatus(1);
//        deviceMapper.updateById(device1);

        mattressMsgService.updateDeviceProperty(id, update.getEndTime(), 1, null, null);

        return Result.ok();

    }

    @Override
    public Result pause(Integer id) {
        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        if (times == null) {
            return Result.fail();
        }

        OrderUseTimes update = new OrderUseTimes();
        update.setId(id);
        update.setStatus(UseOrderStatusEnum.PAUSE.getValue());
        orderUseTimesMapper.updateById(update);

        openClientApi.sendOptions(times.getDeviceCode(), times.getProductKey(), DeviceOptionEnum.pause, null);

        mattressMsgService.updateDeviceProperty(id, null, 0, null, null);

        return Result.ok();
    }

    @Override
    public Result stop(Integer id) {

        log.info("use_times_stop_id=" + id);

        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        if (times == null) {
            return Result.fail();
        }

        openClientApi.sendOptions(times.getDeviceCode(), times.getProductKey(), DeviceOptionEnum.stop, null);

        OrderUseTimes update = new OrderUseTimes();
        update.setId(id);
        update.setStatus(UseOrderStatusEnum.DONE.getValue());
        orderUseTimesMapper.updateById(update);

        //标记设备停止
        Device device = new Device();
        device.setId(times.getDeviceId());
        device.setWorkStatus(0);
        device.setTimesId(0);
        deviceMapper.updateById(device);

        mattressMsgService.unregister(times.getDeviceCode());

        //发放佣金
//        sendBonus(id);
//        GlobalExecutor.executeBySingle(() -> {
//            sendBonus(id);
//        });

        return Result.ok();
    }

    @Override
    public Result changeOption(Integer id, DeviceOptionEnum optionEnum, Integer value) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        if (times == null) {
            return Result.fail();
        }

        openClientApi.sendOptions(times.getDeviceCode(), times.getProductKey(), optionEnum, value);

        if (optionEnum == DeviceOptionEnum.mode &&
                value != null) {

            OrderUseTimes update = new OrderUseTimes();
            update.setId(id);
            update.setMode(value);
            orderUseTimesMapper.updateById(update);

        }

        mattressMsgService.updateDeviceProperty(id, null, null, optionEnum, value);

        return Result.ok();
    }

    @Override
    public Result<Device> deviceInfo(Integer id) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);
        if (times == null) {
            return Result.fail();
        }

//        Device device = deviceMapper.selectById(times.getDeviceId());
        Device device = deviceMapper.selectByDeviceCode(times.getDeviceCode());
        return Result.ok(device);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void insert(OrderUseTimes record) {

        orderUseTimesMapper.insert(record);

        sendBonus(record.getId());
    }

    @Override
    public void sendBonus(Integer id) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);

        this.sendBonus2(times);

    }

    @Override
    public void sendBonus2(OrderUseTimes times) {

        if (times == null) {
            return;
        }

        Integer id = times.getId();

        if (times.getBonusSend() == 1) {
            log.info("send_bonus_already_send,recordId={}", id);
            return;
        }

        if (times.getMoney() <= 0) {
            log.info("send_bonus_is_0,recordId={}", id);
            return;
        }

        Integer merchantId = times.getMerchantId();
        if (merchantId == null ||
                merchantId == Constants.SYS_MERCHANT_ID) {

            //给平台发放佣金
            sendBonusToMember(Constants.SYS_MEMBER_ID, times.getMoney(), times.getMoney(), Constants.ROLE_SYS,
                    Constants.SYS_MERCHANT_ID, merchantId, "平台", "平台", null, id, times.getOrderId(), null, null);

            OrderUseTimes update = new OrderUseTimes();
            update.setId(id);
            update.setMoney(times.getMoney());
            update.setBonusMer(0);
            update.setBonusSale(0);
            update.setBonusSys(times.getMoney());
            update.setBonusSend(1);
            orderUseTimesMapper.updateById(update);

            return;
        }

        Merchant merchant = merchantMapper.selectById(merchantId);
        if (merchant == null) {
            log.info("send_bonus_no_merchant,recordId={},merchantId={}", id, merchantId);
            return;
        }

        MerchantGrade merchantGrade = merchantGradeMapper.selectByLevel(merchant.getGrade());
        if (merchantGrade == null) {
            log.info("send_bonus_no_grade,recordId={},grade={}", id, merchant.getGrade());
            return;
        }

        Integer bonusRatio = merchantGrade.getBonusRatio();
        OrderUseTimes update = new OrderUseTimes();
        update.setId(id);

        Integer money = times.getMoney();
        //商家佣金
        Integer merBonus = MathUtil.discount(money, bonusRatio);
        //平台佣金
        Integer sysBonus = money - merBonus;

        Long orderId = times.getOrderId();

        update.setMoney(money);
        update.setBonusMer(merBonus);

        //给商家发放佣金
        sendBonusToMember(merchant.getMemberId(), money, merBonus, Constants.ROLE_MERCHANT,
                merchantId, merchantId, merchant.getName(), merchant.getName(), merchant.getMobile(), id, orderId, merchant.getGrade(), bonusRatio);

        Integer saleId = merchant.getSaleId();
        Integer investorId = merchant.getInvestorId();
        // 没有服务商
        if (saleId == null) {

            if (investorId == null) {
                //没有投资商
                //给平台分记录
                //平台佣金=核销金额-服务商佣金-商家佣金
                sendBonusToMember(Constants.SYS_MEMBER_ID, money, sysBonus, Constants.ROLE_SYS,
                        0, merchantId, merchant.getName(), "平台", null, id, orderId, null, null);

                update.setBonusSys(sysBonus);
            } else {

                Investor investor = investorMapper.selectById(investorId);
                if (investor == null) {
                    log.info("send_bonus_not_find_investor,investorId={}", merchantId);
                    return;
                }

                //投资商佣金
                Integer investBonus = MathUtil.discount(sysBonus, investor.getBonusRatio());
                //平台佣金
                Integer sysBonus2 = sysBonus - investBonus;

                update.setBonusSys(sysBonus2);
                update.setBonusInvestor(investBonus);

                sendBonusToMember(investor.getMemberId(), sysBonus, investBonus, Constants.ROLE_INVESTOR,
                        investorId, merchantId, merchant.getName(), investor.getName(), investor.getMobile(), id, orderId, null, investor.getBonusRatio());

                sendBonusToMember(Constants.SYS_MEMBER_ID, sysBonus, sysBonus2, Constants.ROLE_SYS,
                        0, merchantId, merchant.getName(), "平台", null, id, orderId, null, null);

            }

            update.setBonusSale(0);
            update.setBonusSend(1);
            orderUseTimesMapper.updateById(update);

            return;
        }

        Sale sale = saleMapper.selectById(saleId);
        if (sale == null) {
            log.info("send_bonus_no_sale,recordId={},saleId={}", id, saleId);
            return;
        }

        if (sale.getPid() == 0) {
            //只有一级销售
            //没有二级销售
            Integer saleBonus = MathUtil.discount(sysBonus, sale.getBonusRatio());

            //给一级销售发放佣金
            log.info("send_bonus_to_top_sale,recordId={},topSaleId={},memberId={},sysBonus={},saleBonus={},orderId={}",
                    id, saleId, sale.getMemberId(), sysBonus, saleBonus, orderId);
            sendBonusToMember(sale.getMemberId(), sysBonus, saleBonus, Constants.ROLE_SALE,
                    saleId, merchantId, merchant.getName(), sale.getName(), sale.getMobile(), id, orderId, null, sale.getBonusRatio());

            update.setBonusSale(saleBonus);

            sysBonus = sysBonus - saleBonus;


        } else {
            //有二级销售

            //拿到一级销售
            Sale topSale = saleMapper.selectById(sale.getPid());
            if (topSale == null) {
                log.info("send_bonus_no_top_sale,recordId={},topSaleId={}", id, sale.getPid());
                return;
            }

            //一级销售总佣金
            Integer saleBonus = MathUtil.discount(sysBonus, topSale.getBonusRatio());

            //子销售佣金
            Integer subBonus = MathUtil.discount(saleBonus, sale.getBonusRatio());

            //一级销售佣金
            Integer topBonus = saleBonus - subBonus;

            update.setBonusSale(saleBonus);

            //平台拿到的佣金
            sysBonus = sysBonus - saleBonus;

            //给一级销售发放佣金
            log.info("send_bonus_to_top_sale,recordId={},topSaleId={},memberId={},sysBonus={},topBonus={},orderId={}",
                    id, topSale.getId(), topSale.getMemberId(), sysBonus, topBonus, orderId);
            sendBonusToMember(topSale.getMemberId(), sysBonus, topBonus, Constants.ROLE_SALE,
                    topSale.getId(), merchantId, merchant.getName(), topSale.getName(), topSale.getMobile(), id, orderId, 0, topSale.getBonusRatio());

            //给二级销售发放佣金
            log.info("send_bonus_to_sub_sale,recordId={},subSaleId={},memberId={},saleBonus={},subBonus={},orderId={}",
                    id, sale.getId(), sale.getMemberId(), saleBonus, subBonus, orderId);
            sendBonusToMember(sale.getMemberId(), saleBonus, subBonus, Constants.ROLE_SUB_SALE,
                    sale.getId(), merchantId, merchant.getName(), sale.getName(), sale.getMobile(), id, orderId, 0, sale.getBonusRatio());

        }

        if (investorId == null) {
            //没有投资商
            //给平台分记录
            //平台佣金=核销金额-服务商佣金-商家佣金
            sendBonusToMember(Constants.SYS_MEMBER_ID, money, sysBonus, Constants.ROLE_SYS,
                    0, merchantId, merchant.getName(), "平台", null, id, orderId, null, null);

            update.setBonusSys(sysBonus);
        } else {

            Investor investor = investorMapper.selectById(investorId);
            if (investor == null) {
                log.info("send_bonus_not_find_investor,investorId={}", merchantId);
                return;
            }

            //投资商佣金
            Integer investBonus = MathUtil.discount(sysBonus, investor.getBonusRatio());
            //平台佣金
            Integer sysBonus2 = sysBonus - investBonus;

            update.setBonusSys(sysBonus2);
            update.setBonusInvestor(investBonus);

            sendBonusToMember(investor.getMemberId(), sysBonus, investBonus, Constants.ROLE_INVESTOR,
                    investorId, merchantId, merchant.getName(), investor.getName(), investor.getMobile(), id, orderId, null, investor.getBonusRatio());

            sendBonusToMember(Constants.SYS_MEMBER_ID, sysBonus, sysBonus2, Constants.ROLE_SYS,
                    0, merchantId, merchant.getName(), "平台", null, id, orderId, null, null);

        }

        update.setBonusSend(1);
        orderUseTimesMapper.updateById(update);

    }

    @Override
    public void backBonus(Integer id) {

        OrderUseTimes times = orderUseTimesMapper.selectById(id);


    }

    @Override
    public Result<List<OrderUseTimes>> reportList(Long memberId) {
        List<OrderUseTimes> list = orderUseTimesMapper.reportByMemberId(memberId);
        return Result.ok(list);
    }

    @Override
    public Result<OrderUseTimes> reportDetail(Integer id) {
        OrderUseTimes times = orderUseTimesMapper.selectById(id);

        if (times == null) {
            return Result.fail();
        }

        Integer results = times.getResults();
        InspectReport inspectReport = inspectReportMapper.selectByTzId(results);
        if (inspectReport != null) {
            times.setInspectReport(inspectReport);
        }

        return Result.ok(times);
    }

    /**
     * @param memberId
     * @param totalMoney 总金额
     * @param bonus      佣金
     * @param type       用户类型
     * @param typeId
     * @param recordId   消费次数ID
     * @param orderId    订单号
     */
    public void sendBonusToMember(Long memberId, Integer totalMoney, Integer bonus, Integer type, Integer typeId,
                                  Integer merchantId, String merchantName,
                                  String name, String mobile,
                                  Integer recordId, Long orderId, Integer grade, Integer bonusRatio) {

        if (bonus <= 0) {
            log.info("send_bonus_to_member,bonus={},type={},typeId={}", bonus, type, typeId);
            return;
        }

        //写记录
        OrderUseTimesBonus recordBonus = new OrderUseTimesBonus();
        recordBonus.setRecordId(recordId);
        recordBonus.setOrderId(orderId);
        recordBonus.setMemberId(memberId);
        recordBonus.setType(type);
        recordBonus.setTypeId(typeId);
        recordBonus.setMerchantId(merchantId);
        recordBonus.setMerchantName(merchantName);
        recordBonus.setName(name);
        recordBonus.setMobile(mobile);
        recordBonus.setMonths(DateUtil.getNowMonth());
        recordBonus.setDates(DateUtil.getNowDay());
        recordBonus.setTotalMoney(totalMoney);
        recordBonus.setBonus(bonus);
        recordBonus.setBonusRatio(bonusRatio);
        recordBonus.setGrade(grade);
        recordBonus.setDone(0);
        orderUseTimesBonusMapper.insert(recordBonus);

        //发佣金
        if (memberId != null) {
            memberMerService.sendBonus(memberId, bonus, orderId, recordId, recordBonus.getId());
        }

    }

}
